/*
 * @Author: crissu 13750782397@163.com
 * @Date: 2024-06-04 01:56:14
 * @LastEditors: crissu 13750782397@163.com
 * @LastEditTime: 2024-06-04 01:58:12
 * @FilePath: /try_concurrence/Patterns/Queuing.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package patterns

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

// buffered channel is a type of queue, Adding queuing prematurely can hide synchronization issues such as deadlocks, we can use the queue to make a limit to processing, in this process when the limit <- struct{}{} is full the queue is wait to be released <-limit, if we remove them the 50 goroutines are created at the same time
// This is a simple example of how to use a buffered channel as a queue to limit the number of goroutines that are created at the same time.
func TryQueuing() {
	var wg sync.WaitGroup
	limit := make(chan interface{}, runtime.NumCPU())

	fmt.Printf("Started, Limit %d\n", cap(limit))

	workers := func(l chan<- interface{}, wg *sync.WaitGroup) {
		for i := 0; i <= 50; i++ {
			i := i

			limit <- struct{}{}
			wg.Add(1)

			go func(x int, w *sync.WaitGroup) {
				defer w.Done()

				time.Sleep(1 * time.Second)
				fmt.Printf("Process %d\n", i)

				<-limit
			}(i, wg)
		}
	}

	workers(limit, &wg)
	wg.Wait()

	fmt.Println("Finished")
}
